
import "ol/ol.css";
import { Map, View, Feature } from "ol";
import Overlay from "ol/Overlay";
import { defaults } from "ol/control";

import VectorLayer from "ol/layer/Vector";
import Vector from "ol/source/Vector";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
import { OSM } from "ol/source";


import { Style, Circle, Fill, Stroke, Text } from "ol/style";
import {
    Point,
    LineString,
    Polygon,
    MultiPolygon
} from "ol/geom";

import { Draw, Modify, Select, defaults as de } from "ol/interaction";
import { getArea, getLength } from "ol/sphere";
import { unByKey } from "ol/Observable";
import WKT from "ol/format/WKT";

import Styles from "@/openlayers/Styles";

import GeoJSON from 'ol/format/GeoJSON';

//windyjs
import { WindLayer } from "ol-wind";
import gfs from "@/assets/data/gfs.json"

export default class MyMap {
    map
    pointsLayer //标记点 图层

    newAreaLayer//新增标记面 图层
    areasLayer //标记面图层

    clickEventEditFeature //编辑点面事件

    measureTooltipElement//测量提示element
    measureTooltip //测量提示弹框Overlay

    //初始地图
    constructor(target, center) {
        this.layers = this.createBaseLayers()
        //地图加载
        this.map = new Map({
            interactions: de({ doubleClickZoom: false }),
            controls: defaults({
                attribution: false,
                rotate: false,
                zoom: false,
            }),
            target,
            layers: this.createBaseLayers(),
            overlays: [],
            view: this.createBaseView(center)
        });

    }

    //创建图层
    createBaseLayers() {
        const tiandi_base_map = new TileLayer({
            source: new XYZ({
                name: "天地图-矢量底图",
                url: "http://t0.tianditu.com/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk=2f14d8bf45e4b370a5daca14d61e2e10",
                projection: "EPSG:4326",
            }),
            visible: true
        });
        const tiandi_image_map = new TileLayer({
            source: new XYZ({
                name: "天地图-影像底图",
                url: "http://t0.tianditu.com/DataServer?T=img_c&x={x}&y={y}&l={z}&tk=2f14d8bf45e4b370a5daca14d61e2e10",
                projection: "EPSG:4326",
            }),
            visible: false
        });

        const tiandi_base_tag_map = new TileLayer({
            source: new XYZ({
                name: "天地图-矢量标记",
                url: "http://t0.tianditu.com/DataServer?T=cva_c&x={x}&y={y}&l={z}&tk=2f14d8bf45e4b370a5daca14d61e2e10",
                projection: "EPSG:4326",
            }),
            visible: true
        });
        // const tiandi_image_tag_map = new TileLayer({
        //     source: new XYZ({
        //         name: "天地图-影像标记",
        //         url: "http://t0.tianditu.com/DataServer?T=cia_c&x={x}&y={y}&l={z}&tk=2f14d8bf45e4b370a5daca14d61e2e10",
        //         projection: "EPSG:4326",

        //     }),
        //     visible: false
        // });
        return [tiandi_base_map, tiandi_image_map, tiandi_base_tag_map]
    }
    //创建视图
    createBaseView(center) {
        const view = new View({
            //经度 纬度
            center,
            //指定投影EPSG:4326，等同于WGS84坐标系
            projection: 'EPSG:4326',

            //设置地图中心范围
            //经度29度到31度，纬度在102到104度之间
            //[minX, minY, maxX, maxY]
            // extent: [120, 29, 122, 36],

            //层级
            zoom: 10,
            minZoom: 1,
            maxZoom: 20
        });
        return view
    }
    //移动视图
    animateViewCenter(center) {
        this.map.getView().animate({
            center, // 中心点
            zoom: 14, // 缩放级别
            duration: 1000, // 缩放持续时间，默认不需要设置
        });
    }
    //移动视图
    animateViewGeom(geom) {
        let format = new WKT();
        let feature = format.readFeature(geom, {
            dataProjection: "EPSG:4326",
            featureProjection: "EPSG:4326",
        });
        var geo = feature.getGeometry();
        var extent = geo.getExtent();
        this.map.getView().fit(extent, {
            duration: 2000, //动画的持续时间,
            // maxZoom: 18
        });
    }

    //测距、测面、打点
    measure(type) {
        const source = new Vector();
        const vector = new VectorLayer({
            source: source,
            style: new Style({
                fill: new Fill({
                    color: 'rgba(255, 255, 255, 0.2)',
                }),
                stroke: new Stroke({
                    color: '#ffcc33',
                    width: 2,
                }),
                image: new Circle({
                    radius: 7,
                    fill: new Fill({
                        color: '#ffcc33',
                    }),
                }),
            }),
        });
        this.map.addLayer(vector)

        //打点
        if (type === 'Point') {
            // 绑定事件
            const clickEvent = this.map.on("singleclick", (event) => {
                // 创建feature
                const feature = new Feature({
                    geometry: new Point(event.coordinate),
                });
                //设置样式
                const styles = new Styles();
                feature.setStyle(styles.createPointStyle(event.coordinate.toString()));
                vector.getSource().addFeatures([feature]);

                const wkt = new WKT().writeGeometry(new Point(event.coordinate), {
                    dataProjection: "EPSG:4326",
                    featureProjection: "EPSG:4326",
                });
                console.log({ wkt, coordinate: event.coordinate });
                unByKey(clickEvent);
            });
            return
        }

        //测面、距
        const draw = new Draw({
            source: source,
            type: type,
            stopClick: true, //绘制时 停止为地图添加的click, singleclick, doubleclick 事件。
            style: new Style({
                fill: new Fill({
                    color: 'rgba(255, 255, 255, 0.2)',
                }),
                stroke: new Stroke({
                    color: 'rgba(0, 0, 0, 0.5)',
                    lineDash: [10, 10],
                    width: 2,
                }),
                image: new Circle({
                    radius: 5,
                    stroke: new Stroke({
                        color: 'rgba(0, 0, 0, 0.7)',
                    }),
                    fill: new Fill({
                        color: 'rgba(255, 255, 255, 0.2)',
                    }),
                }),
            }),
        });
        this.map.addInteraction(draw);

        this.map.addOverlay(this.createMeasureTooltip());
        let listener, sketch;
        draw.on('drawstart', (evt) => {
            sketch = evt.feature;
            let geometry = sketch.getGeometry();

            let tooltipCoord = evt.coordinate;
            listener = geometry.on('change', evt => {
                let geom = evt.target;
                let output;
                if (geom instanceof Polygon) {
                    output = this.formatArea(geom);
                    tooltipCoord = geom.getInteriorPoint().getCoordinates();
                } else if (geom instanceof LineString) {
                    output = this.formatLength(geom);
                    tooltipCoord = geom.getLastCoordinate();
                }
                this.measureTooltipElement.innerHTML = output;
                this.measureTooltip.setPosition(tooltipCoord);
            });
        });

        draw.on('drawend', () => {
            this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';
            this.measureTooltip.setOffset([0, -7]);
            sketch = null;
            this.measureTooltipElement = null;
            this.map.removeInteraction(draw);
            unByKey(listener);
        });
    }
    //创建测距、测面时的提示框
    createMeasureTooltip() {
        if (this.measureTooltipElement) {
            this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement);
        }
        this.measureTooltipElement = document.createElement('div');
        this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
        this.measureTooltip = new Overlay({
            element: this.measureTooltipElement,
            offset: [0, -15],
            positioning: 'bottom-center',
            stopEvent: false,
            insertFirst: false,
        });
        return this.measureTooltip
    }
    formatArea(polygon) {
        const area = getArea(polygon, { projection: 'EPSG:4326' });
        let output;
        if (area > 10000) {
            output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>';
        } else {
            output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>';
        }
        return output;
    }
    formatLength(line) {
        const length = getLength(line, { projection: 'EPSG:4326' });
        let output;
        if (length > 100) {
            output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km';
        } else {
            output = Math.round(length * 100) / 100 + ' ' + 'm';
        }
        return output;
    }

    //显示点
    showPoints(data) {
        if (this.pointsLayer) {
            this.map.removeLayer(this.pointsLayer);
        }
        const styles = new Styles();
        let features = [];
        data.forEach((item) => {
            const feature = new Feature({
                geometry: new Point(item),
            });
            feature.setProperties(item);
            feature.setStyle(styles.createPointStyle(item.name));
            features.push(feature);
        });
        this.pointsLayer = new VectorLayer({
            source: new Vector({
                features,
            }),
        });
        this.map.addLayer(this.pointsLayer);
    }
    //添加点
    addPoint() {
        // 设置添加标记点图层
        const pointLayer = new VectorLayer({
            source: new Vector(),
        });
        this.map.addLayer(pointLayer);

        // 绑定事件
        const clickEvent = this.map.on("singleclick", (event) => {
            // 创建feature
            const feature = new Feature({
                geometry: new Point(event.coordinate),
            });
            //设置 图表的样式
            const styles = new Styles();
            feature.setStyle(styles.createPointStyle('测试点'));
            pointLayer.getSource().clear();
            pointLayer.getSource().addFeatures([feature]);

            // 站点转换为WKT格式 POINT(120.884526116333 32.0249844342041)
            const wkt = new WKT().writeGeometry(new Point(event.coordinate), {
                dataProjection: "EPSG:4326",
                featureProjection: "EPSG:4326",
            });
            console.log({ wkt, coordinate: event.coordinate });
            unByKey(clickEvent);
        });
    }
    // 显示面
    showArea(data) {
        if (this.areasLayer) {
            this.map.removeLayer(this.areasLayer);
        }
        let areaList = [];
        data.forEach((wkt) => {
            let feature = new WKT().readFeature(wkt, {
                dataProjection: "EPSG:4326",
                featureProjection: "EPSG:4326",
            });
            const styles = new Styles();
            feature.setStyle(styles.getAreaStyle());
            feature.setProperties(wkt);
            areaList.push(feature);
        });
        this.areasLayer = new VectorLayer({
            source: new Vector({
                features: [...areaList],
            }),
        });
        this.map.addLayer(this.areasLayer);
    }
    // 添加面
    addArea() {
        //新增标记面
        this.newAreaLayer = new VectorLayer({
            source: new Vector(),
        });
        this.map.addLayer(this.newAreaLayer);

        this.draw = new Draw({
            type: "MultiPolygon",
            source: this.newAreaLayer.getSource(),
        });
        this.map.addInteraction(this.draw);

        this.draw.once("drawend", (event) => {
            const wkt = new WKT().writeGeometry(
                new MultiPolygon(event.feature.getGeometry().getCoordinates()),
                {
                    dataProjection: "EPSG:4326",
                    featureProjection: "EPSG:4326",
                }
            );
            console.log(wkt);

            this.map.removeInteraction(this.draw);
            this.draw = null

            //可修改面
            this.editArea(this.newAreaLayer);
        });
    }
    //编辑面
    editArea(layer) {
        let select = new Select({ layers: [layer] });
        let features = select.getFeatures();
        let modify = new Modify({
            features: features,
        });
        select.setActive(true);
        modify.setActive(true);

        this.select = select;
        this.modify = modify;

        this.map.addInteraction(this.select);
        this.map.addInteraction(this.modify);

        features.on("add", (event) => {
            const feature = event.element;
            feature.on("change", (evt) => {
                const wkt = new WKT().writeGeometry(
                    new MultiPolygon(evt.target.getGeometry().getCoordinates()),
                    {
                        dataProjection: "EPSG:4326",
                        featureProjection: "EPSG:4326",
                    }
                );
                console.log(wkt);
            });
        });
    }
    //取消编辑面
    cancelEditArea() {
        this.map.removeInteraction(this.select);
        this.map.removeInteraction(this.modify);
        this.select = null
        this.modify = null
    }
    //添加线段
    addLine() {
        // 设置添加标记线图层
        const newLineLayer = new VectorLayer({
            source: new Vector(),
            style: new Style({
                //线条宽度、颜色
                stroke: new Stroke({
                    color: '#00008B',
                    width: 5
                })
            })
        })
        this.map.addLayer(newLineLayer)
        const draw = new Draw({
            type: 'LineString',
            source: newLineLayer.getSource()
        })
        this.map.addInteraction(draw)
        draw.on('drawend', (event) => {
            const wkt = new WKT().writeGeometry(new LineString(event.feature.getGeometry().getCoordinates()), {
                dataProjection: 'EPSG:4326',
                featureProjection: 'EPSG:4326'
            })
            console.log(wkt);
            this.map.removeInteraction(draw)
            this.editLine(newLineLayer);
        })
    }
    //编辑线段
    editLine(layer) {
        let select = new Select({ layers: [layer] });
        let features = select.getFeatures();
        let modify = new Modify({
            features: features,
        });
        select.setActive(true);
        modify.setActive(true);

        this.select = select;
        this.modify = modify;

        this.map.addInteraction(this.select);
        this.map.addInteraction(this.modify);
        features.on("add", (event) => {
            const feature = event.element;
            feature.on("change", (evt) => {
                const wkt = new WKT().writeGeometry(
                    new LineString(evt.target.getGeometry().getCoordinates()),
                    {
                        dataProjection: "EPSG:4326",
                        featureProjection: "EPSG:4326",
                    }
                );
                console.log(wkt);
            });
        });
    }
    cancelEditLine() {
        this.map.removeInteraction(this.select);
        this.map.removeInteraction(this.modify);
        this.select = null
        this.modify = null
    }


    //选中编辑Featur
    clickFeature() {
        this.clickEventEditFeature = this.map.on(
            "click",
            (evt) => {
                let flag = false;
                this.map.forEachFeatureAtPixel(evt.pixel, (a) => {
                    console.log('a: ', a)
                    const type = a.getGeometry().getType(); // Point、MultiPolygon、LineString
                    if (type === "Point") {
                        console.log('选中修改点');
                    } else if (type === "MultiPolygon") {
                        console.log('选中修改面');
                        // this.editArea(this.areasLayer);
                    } else if (type === "LineString") {
                        console.log("线修改线");
                    }
                });
            },
            { hitTolerance: 180 } //hitTolerance: 以css像素为单位的命中检测公差。在给定位置周围半径内的像素将被检查特征。
        );

    }

    //添加流动线
    addMovingLine() {
        const geojsonObject = {
            "type": "FeatureCollection",
            "features": [
                {
                    "type": "Feature",
                    "properties": {},
                    "geometry": {
                        "coordinates": [
                            [
                                120.59608927696371,
                                31.06202073831048
                            ],
                            [
                                120.63149446427894,
                                31.07331888747879
                            ],
                            [
                                120.68147825813776,
                                31.07510268306622
                            ],
                            [
                                120.77519787161987,
                                31.08818282802015
                            ],
                            [
                                120.812685717014,
                                31.127412459737243
                            ],
                            [
                                120.84114871073785,
                                31.114932062363565
                            ]
                        ],
                        "type": "LineString"
                    }
                }
            ]
        }

        const source = new Vector({
            features: new GeoJSON().readFeatures(geojsonObject)
        });

        let style = [
            //实线
            new Style({
                stroke: new Stroke({
                    color: "rgba(30,144,255, 1)",
                    width: 3,
                    lineDash: [0]
                }),
                text: new Text({
                    text: '流动效果',
                    fill: new Fill({
                        color: '#000',
                    }),
                    font: "18px Arial",
                    offsetY: 20,
                    placement: "line"
                }),
            }),
            //虚线
            new Style({
                stroke: new Stroke({
                    color: [255, 250, 250, 1],
                    width: 3,
                    lineDash: [20, 27], //一组线段和间距交互的数组，可以控制虚线的长度
                    lineDashOffset: 0
                })
            })
        ];

        const vectorlayer = new VectorLayer({
            source,
            style
        })
        this.map.addLayer(vectorlayer);

        //定时赋值
        setInterval(() => {
            let lineDashOffset = vectorlayer.getStyle()[1].getStroke().getLineDashOffset();
            vectorlayer.setStyle(
                [
                    vectorlayer.getStyle()[0],
                    //虚线
                    new Style({
                        stroke: new Stroke({
                            color: [204, 204, 255, 1],
                            width: 3,
                            lineDash: [10, 25],
                            lineDashOffset: lineDashOffset == 100 ? 0 : lineDashOffset + 2
                        })
                    })]
            )
        }, 50)
    }

    addWindy() {
        const windLayer = new WindLayer(gfs, {
            //在鼠标交互时始终显示粒子
            forceRender: true,

            //风场参数
            windOptions: {
                globalAlpha: 0.9,//全局透明度，主要影响粒子路径拖尾效果 默认0.9
                lineWidth: 3, // 粒子路径宽度，默认1, 当为回调函数时，参数function(m:对应点风速值) => number
                colorScale: () => {  //粒子颜色配置  当为回调函数时，参数function(m:对应点风速值) => string
                    return "#00b3ef"
                },
                velocityScale: 1 / 100,  // 粒子速度 对于粒子路径步长的乘积基数
                maxAge: 10,  // 粒子路径能够生成的最大帧数
                paths: 800, //生成的粒子路径数量
                frameRate: 20,  //帧率（ms）
            },

            //数据配置项 todo
            fieldOptions: {

            }
        });
        this.map.addLayer(windLayer);
    }

}